from os import environ, system
from os.path import exists

from validators import url as check_url

from .current import CurrentEdit
from .notify import Notify
from .funcs import numType, setimg


class ModeData():
    def __init__(self):
        super(ModeData, self).__init__()
        self.value = CurrentEdit()
        self.notify = Notify()
        self.path = f'{environ["HOME"]}/.cache/anima'
        self.down = f'{self.path}/downloads'

    def edited(self, data, mode, tab, index, spin, text):
        """ Editing value for list manga or ranobe. """
        child = ('series', 'numbers', 'chapters')[tab]
        notify = data['notify']['notify']

        val = f'{spin[0].value()}.{spin[1].value()}'

        if float(val) > 0:
            value = int(numType(val)) if '.0' in val else numType(val)
            data[mode][child][index] = value
            data = self.notify.check(data, mode, text, value)
            notify = data['notify']['notify'] = 'empty' \
                if self.notify.empty(data) else data['notify']['notify']

        return data, notify

    def __handle(self, msg, edit):
        """ Handle error in lineEdit. """
        system(msg)
        edit.setStyleSheet('background: rgb(236, 0, 0)')
        edit.setText('  ERROR check URL..')

    def saved(self, data, mode, tab, spin, edit, check, link, ind):
        """ Saving URL in one from lists: anime, manga or ranobe. """
        tab = 0 if check and not ind else 1 if check else tab
        mode = 'anime' if check and not ind else 'manga' if check else mode

        ico = f"icons/{('animevost', 'mask', 'ranobe')[tab]}.png"
        catch = ('log', "logs", 'track-name', 'track-link', 'ended')
        track = (data['anime']['track-link'], *data['manga']['track-link'])
        names = (data['anime']['track-name'], *data['manga']['track-name'])

        val = float(f'{spin[0].value()}.{spin[1].value()}') \
                        if spin[1].value() else spin[0].value()
        url = track[ind][link] if check and track else edit.text()
        title = ' '.join(names[ind][link].split(' - ')[:-1]) if names and \
                    check and ind == 3 else names[ind][link].split(' / ')[0] \
                    if names and check else ''
        dicts = {0: url, 1: val, 2: val, 3: 0, 4: 0, 5: title, 7: '', 8: ico} \
            if tab == 0 else \
                {0: url, 1: val, 2: 0, 3: title, 6: '', 5: ico} \
            if tab == 1 else \
                {0: url, 2: val, 3: 0, 4: 0, 1: '', 5: '', 6: ico}

        if check_url(url):
            if url not in data[mode]['urls']:
                edit.setStyleSheet('background: rgb(98, 255, 59)')
                [data[mode][v].append(dicts[i])
                    for i, v in enumerate(data[mode]) if v not in catch]
                data[mode]['ended'].append('ongoing')
            else:
                self.__handle(f'notify-send "{mode} already exists"', edit)
        else:
            self.__handle(f'notify-send "Error add {mode}"', edit)
        return data

    def __stoped(self, tools, stop=False):
        if stop is False:
            tools[0].clear()
            [i.setIcon(setimg(f'{self.path}/{tools[3]}')) for i in tools[1:3]]
            return False
        return True

    def changed(self, mode, combo, lcd, label, but,
                      txt, tab, data, prev):
        """ Changing values in comboboxes. """
        child = ('series', 'numbers', 'chapters')[tab]
        stop = True if data[mode][child] else False
        twin = ('look', 'change_numbers', 'access-chapters')[tab]
        index = combo.currentIndex()
        images, raw = f'icons/error.png', 'error.png'

        if self.__stoped((combo, prev, label, images), stop):
            fraction = data['anime']['ova'][index] if tab == 0 else 0
            num = f"{data[mode][child][index]}.{fraction}" if tab == 0 else 0
            now = data[mode][child][index] if tab in (1,2) else float(num)
            view = (now, data[mode][twin][index])
            name = 'names' if tab in (1, 2) else 'name'

            combo.setToolTip(data[mode][name][index])
            if exists(f'{self.path}/{data[mode]["images"][index]}'):
                raw = data[mode]["images"][index].split('/')[-1]
                images = data[mode]["images"][index]
            prev.setIcon(setimg(f'{self.path}/{images}'))
            label.setIcon(setimg(f'{self.path}/description/raw/{raw}'))
            txt.setHtml(data[mode]['description'][index].replace('\n', '<br>'))

            [v.display(view[i]) for i, v in enumerate(lcd)]
            one, two = data[mode][child][index], data[mode][twin][index]

            colors = ('#32e925', '#c01010', '#8D57C6', '#0D57C6')
            back = {'ongoing': 0 if one == two else 1, 'stoped': 2, 'end': 3}
            background = colors[back[data[mode]['ended'][index]]]
            lcd[1].setStyleSheet(f'background: {background}')

            lst = [f'{i.value()}'.split('.') for i in lcd]
            cur, fut = [tuple(map(lambda i: int(i), j)) for j in lst]

            but.setEnabled(False if cur == fut else True)

    def deleted(self, data, mode, tab, index, save):
        """ Delete one item from lists: anime, manga or ranobe. """
        catch = ('log', 'logs', 'track-link', 'track-name')
        name = 'names' if tab in (1,2) else 'name'
        ico = ('animevost', 'mask', 'ranobe')[tab]
        icon, notify = f'icons/{ico}.png', data['notify']['notify']

        dirs = "_".join(data[mode][name][index].split())

        if save:
            data['history'][mode].append(data[mode][name][index])
            mv = 'mv "{0}/{1}" "{0}/history/"'.format(self.down, dirs)

        rm = f'rm -r "{self.down}/{dirs}"'
        system(mv if save else rm) if tab == 0 else None
        remove = f'rm {self.path}/{data[mode]["images"][index]}'
        system(remove) if  data[mode]["images"][index] != icon else True
        data = self.notify.check(data, mode, data[mode][name][index])
        notify = data['notify']['notify'] = 'empty' \
            if self.notify.empty(data) else data['notify']['notify']
        [data[mode][i].pop(index) for i in data[mode] if i not in catch]

        return data, notify
